package com.dwj.generator.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.dwj.generator.common.enums.ProjectType;
import com.dwj.generator.common.response.Response;
import com.dwj.generator.config.generator.DwjFileOutConfig;
import com.dwj.generator.config.generator.DwjInjectionConfig;
import com.dwj.generator.config.generator.DwjTemplateEngine;
import com.dwj.generator.model.project.ProjectDetail;
import com.dwj.generator.model.project.ProjectTemplateDto;
import com.dwj.generator.service.IProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: dangweijian
 * @description:
 * @create: 2021-03-29 16:37
 **/
@RestController
@RequestMapping("/api/generator")
public class GeneratorController {

    @Resource
    private IProjectService projectService;
    @Autowired
    private FileController fileController;

    @PostMapping("/generate/{projectId}")
    public Response<Map> generate(@PathVariable Long projectId, @RequestBody List<String> tables, HttpServletResponse response) throws IOException {
        //获取项目配置
        ProjectDetail projectDetail = projectService.detail(projectId);
        String tablePrefix = projectDetail.getTablePrefix();
        if (StrUtil.isNotBlank(tablePrefix) && tablePrefix.endsWith("_")) {
            tablePrefix = tablePrefix.substring(0, tablePrefix.length() - 1);
        }
        String fieldPrefix = projectDetail.getColumnPrefix();
        if (StrUtil.isNotBlank(fieldPrefix) && fieldPrefix.endsWith("_")) {
            fieldPrefix = fieldPrefix.substring(0, fieldPrefix.length() - 1);
        }

        AutoGenerator mpg = new AutoGenerator();

        //基础配置
        GlobalConfig gc = new GlobalConfig();
        gc.setOutputDir(projectDetail.getRootPath());
        gc.setAuthor("easy-generator");
        gc.setOpen(false);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setFileOverride(true);
        mpg.setGlobalConfig(gc);

        //数据库配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://" + projectDetail.getDatabase().getHost() + ":" + projectDetail.getDatabase().getPort() + "/" + projectDetail.getDatabase().getDbName() + "?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC");
        dsc.setDriverName(projectDetail.getDatabase().getDrive());
        dsc.setUsername(projectDetail.getDatabase().getUsername());
        dsc.setPassword(projectDetail.getDatabase().getPassword());
        mpg.setDataSource(dsc);
        mpg.setCfg(new DwjInjectionConfig(projectDetail.getProjectTemplates()));

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.valueOf(projectDetail.getTableNameStyle()));
        strategy.setColumnNaming(NamingStrategy.valueOf(projectDetail.getColumnNameStyle()));
        strategy.setEntityLombokModel(projectDetail.isUseLombok());
        strategy.setRestControllerStyle(ProjectType.SPRING_BOOT.equals(projectDetail.getProjectType()));
        strategy.setInclude(tables.toArray(new String[0]));
        strategy.setTablePrefix(tablePrefix);
        strategy.setFieldPrefix(fieldPrefix);
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new DwjTemplateEngine());
        mpg.execute();
        return Response.success("代码生成完毕，请到相应目录查看！");
    }

    @GetMapping("/down/{projectId}")
    public void down(@PathVariable Long projectId, HttpServletResponse response) throws IOException {
        //获取项目配置
        ProjectDetail projectDetail = projectService.detail(projectId);
        String root = GeneratorController.class.getClassLoader().getResource("./").getPath();
        if (root.endsWith("target/classes/")) {
            root = root.replace("target/classes/", "");
            root = root + projectDetail.getRootPath().replace("./", "");
            ZipUtil.zip(root + "/" + projectId);
        } else {
            ZipUtil.zip(projectDetail.getRootPath() + "/" + projectId);
        }
        response.setContentType("application/zip");
        // 设置响应头，告诉浏览器这是一个附件，并指定文件名
        String headerValue = String.format("attachment; filename=\"%s.zip\"", "myArchive");
        response.setHeader("Content-Disposition", headerValue);
        // 获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
        try (FileInputStream inputStream = new FileInputStream(root + "/" + projectId + ".zip")) {
            // 将文件内容写入到输出流中
            byte[] buffer = new byte[4096]; // 使用缓冲流来避免内存消耗
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
        outputStream.close();
    }

    @PostMapping("/views/{projectId}")
    public Response<Map> views(@PathVariable Long projectId, @RequestBody List<String> tables) {
        //获取项目配置
        ProjectDetail projectDetail = projectService.detail(projectId);
        String tablePrefix = projectDetail.getTablePrefix();
        if (StrUtil.isNotBlank(tablePrefix) && tablePrefix.endsWith("_")) {
            tablePrefix = tablePrefix.substring(0, tablePrefix.length() - 1);
        }
        String fieldPrefix = projectDetail.getColumnPrefix();
        if (StrUtil.isNotBlank(fieldPrefix) && fieldPrefix.endsWith("_")) {
            fieldPrefix = fieldPrefix.substring(0, fieldPrefix.length() - 1);
        }

        AutoGenerator mpg = new AutoGenerator();

        //基础配置
        GlobalConfig gc = new GlobalConfig();
        gc.setOutputDir(projectDetail.getRootPath());
        gc.setAuthor("easy-generator");
        gc.setOpen(false);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setFileOverride(true);
        mpg.setGlobalConfig(gc);

        //数据库配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://" + projectDetail.getDatabase().getHost() + ":" + projectDetail.getDatabase().getPort() + "/" + projectDetail.getDatabase().getDbName() + "?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC");
        dsc.setDriverName(projectDetail.getDatabase().getDrive());
        dsc.setUsername(projectDetail.getDatabase().getUsername());
        dsc.setPassword(projectDetail.getDatabase().getPassword());
        mpg.setDataSource(dsc);
        mpg.setCfg(new DwjInjectionConfig(projectDetail.getProjectTemplates()));

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.valueOf(projectDetail.getTableNameStyle()));
        strategy.setColumnNaming(NamingStrategy.valueOf(projectDetail.getColumnNameStyle()));
        strategy.setEntityLombokModel(projectDetail.isUseLombok());
        strategy.setRestControllerStyle(ProjectType.SPRING_BOOT.equals(projectDetail.getProjectType()));
        strategy.setInclude(tables.toArray(new String[0]));
        strategy.setTablePrefix(tablePrefix);
        strategy.setFieldPrefix(fieldPrefix);
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new DwjTemplateEngine());
        mpg.execute();

        InjectionConfig injectionConfig = mpg.getCfg();
        ConfigBuilder configBuilder = injectionConfig.getConfig();
        List<TableInfo> tableInfos = configBuilder.getTableInfoList();
        // 获取所有模板信息
        List<ProjectTemplateDto> projectTemplates = projectDetail.getProjectTemplates();
        Map<String, String> files = new HashMap<>();
        tableInfos.forEach(tableInfo -> {
            projectTemplates.forEach(projectTemplate -> {
                // 获取模板信息
                String file = projectTemplate.getOutputPath();
                String fileName = "";
                DwjFileOutConfig dwjFileOutConfig = new DwjFileOutConfig(projectTemplate);
                fileName += dwjFileOutConfig.getFileName(tableInfo);
                fileName += dwjFileOutConfig.getFileExpandName(tableInfo);
                file += "/" + fileName;
                files.put(fileName, file);
            });
        });
        // 返回生成文件信息
        return Response.success(files);
    }


}
